﻿using FineUICoreDesigner;
using FineUICoreDesigner.Base;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.ComponentModel;

namespace FineUIDesignerVSIX.Handle
{
    public class WeformFunctionHandle : IWeformAfterSave
    {
        /// <summary>
        /// 模板
        /// </summary>
        private const string FunctionTemplate = @"
            protected void $EventName$(object sender, EventArgs e)
            {
            }
            ";

        /// <summary>
        /// 模板
        /// </summary>
        private const string FunctionTemplateAsync = @"
            protected async Task $EventName$Async(object sender, EventArgs e)
            {
            }
            ";

        private string pattern = @"<f:[\w\s=""@.]*?\sOnClick=""(?:(?<handler>@Url\.Handler\(""(?<functionName>[^""]+)""\))|(?<functionName>[^""]+))";

        public void Handle(WebformFileInfo editFileInfo)
        {
            var cspath = editFileInfo.FileRootPath + "\\" + editFileInfo.CsFileName;
            var code = BaseHelp.GetCode(cspath);
            if (string.IsNullOrEmpty(code)) return;
            SyntaxTree tree = CSharpSyntaxTree.ParseText(code);
            CompilationUnitSyntax root = tree.GetCompilationUnitRoot();
            var firstClass = root.DescendantNodes()
                            .OfType<ClassDeclarationSyntax>()
                            .FirstOrDefault();
            if (firstClass != null)
            {
                var methods = FindEvents(editFileInfo.FileContent);
                root = AddMethods(editFileInfo, root, firstClass, methods);
            }
        }

        /// <summary>
        /// 新增方法
        /// </summary>
        /// <param name="editFileInfo"></param>
        /// <param name="cspath"></param>
        /// <param name="root"></param>
        /// <param name="firstClass"></param>
        /// <param name="newMethods"></param>
        /// <param name="methods"></param>
        /// <returns></returns>
        private static CompilationUnitSyntax AddMethods(WebformFileInfo editFileInfo, CompilationUnitSyntax root, ClassDeclarationSyntax firstClass, List<string> methods)
        {
            var newMethods = new List<MemberDeclarationSyntax>();
            var cspath = editFileInfo.FileRootPath + "\\" + editFileInfo.CsFileName;
            foreach (var item in methods)
            {
                // 检查是否已存在目标方法
                bool methodExists = false;
                foreach (var member in firstClass.Members)
                {
                    if (member is MethodDeclarationSyntax method && method.Identifier.Text == item)
                    {
                        methodExists = true;
                        break;
                    }
                }
                if (!methodExists)
                {
                    var funtemp = GetFunTemp(firstClass);
                    var methodCode = funtemp.Replace("$EventName$", item);
                    BaseHelp.OutputLine($"生成方法 {item} ");
                    MethodDeclarationSyntax newMethod = SyntaxFactory.ParseMemberDeclaration(methodCode) as MethodDeclarationSyntax;
                    newMethods.Add(newMethod.NormalizeWhitespace());
                }
            }
            if (newMethods.Any())
            {
                root = root.ReplaceNode(firstClass, firstClass.AddMembers(newMethods.ToArray()));
                // 重新生成代码
                string newCode = root.NormalizeWhitespace().ToFullString();
                BaseHelp.WriteAllText(cspath, newCode);
                BaseHelp.OutputLine($"添加事件 {editFileInfo.CsFileName} 成功 👏");
            }

            return root;
        }

        private static string GetFunTemp(ClassDeclarationSyntax firstClass)
        {
            var funtemp = FunctionTemplate;
            if (firstClass != null)
            {
                var pageLoadMethod = firstClass.DescendantNodes()
                                               .OfType<MethodDeclarationSyntax>()
                                               .FirstOrDefault(m => m.Identifier.Text == "Page_LoadAsync");
                if (pageLoadMethod != null)
                {
                    bool isAsync = pageLoadMethod.Modifiers.Any(SyntaxKind.AsyncKeyword);
                    string returnType = pageLoadMethod.ReturnType.ToString();

                    if (isAsync && returnType == "Task")
                    {
                        Console.WriteLine("Page_Load is async Task");
                        funtemp = FunctionTemplateAsync;
                    }
                }
            }
            return funtemp;
        }

        private List<string> FindEvents(string fileContent)
        {
            List<string> events = new List<string>();
            MatchCollection matches = Regex.Matches(fileContent, pattern);
            foreach (Match match in matches)
            {
                string functionName = match.Groups["functionName"].Value;
                string handler = match.Groups["handler"].Value;

                events.Add(functionName);
            }
            return events;
        }
    }
}
